#include "stdafx.h"
#include "ImportData.h"
#include <string>
#include <sstream>
#include <vmmlib/matrix.hpp>
#include <vmmlib/vector.hpp>
using namespace std;

ImportData::ImportData(void)
{
	STEP_SIZE = 0.005;
}

void ImportData::setSize(int s){
	this->size = s;
}

int ImportData::getSize(){
	return this->size;
}

vmml::vector<3,int> ImportData::getAxes(){
	return this->axes;
}

int ImportData::getHeight(){
	return this->height;
}

int ImportData::getWidth(){
	return this->width;
}

int ImportData::getDepth(){
	return this->depth;
}

void ImportData::createDataVolume(int xSize,int ySize,int zSize){
	this->volume = new DataPoint**[xSize];
	
	int ax[] = {xSize,ySize,zSize};
	this->width = zSize;
	this->height = ySize;
	this->depth = xSize;
	this->axes = ax;

	cout << this->axes << endl;

	//Initialize volumespace
	for(int i = 0; i < xSize; i++){
		volume[i] = new DataPoint*[ySize];
		for(int j = 0;j < ySize;j++){
			volume[i][j] = new DataPoint[zSize];
		}
	}

	string** data = this->getData();
	//Fill in volume with points
	float x,y,z;
	for(int i = 1; i< this->getSize();i++){
		string str1 = data[i][4]; 
		string str2 = data[i][5]; 
		string str3 = data[i][6]; 

		stringstream(str1) >> x;
		stringstream(str2) >> y;
		stringstream(str3) >> z;

		vmml::vector<3,int> tmpindx = getIndex(x,y,z);
		vmml::vec3d* flow = new vmml::vec3d;
		vmml::matrix<3,3,double>* dflow = new vmml::matrix<3,3,double>;
	

		for(int k = 0;k<3;k++){
			flow->at(k) = toNumber(data[i][k+1]);
		}

		for(int k = 0;k<3;k++){
			for(int l = 0;l<3;l++){
				dflow->at(k,l) = toNumber(data[i][k*3+l+7]);
			}
		}

		double ftle = toNumber(data[i][16]);

		int ix = tmpindx.x();
		int iy = tmpindx.y();
		int iz = tmpindx.z();

		volume[ix][iy][iz] = DataPoint(flow,dflow,ftle);
	}
	int c = 0;
	for(int i = 0; i < xSize; i++){
		for(int j = 0;j < ySize;j++){
			for(int k = 0; k < zSize;k++){
				//count datapoints
				if(!volume[i][j][k].isEmpty()){
					c+= 1;
				}
			}
		}
	}
	cout << "Non-Empty DataPoints: " << c << endl;
}

double ImportData::toNumber(string str){
	double n = 0;
	stringstream(str) >> n;
	return n;
}

vmml::vector<3,int> ImportData::getIndex(double x, double y, double z){

	double xMin = -0.0475;
	double yMin = -0.0475;
	double zMin = -0.0975;
	
	vmml::vector< 3, int > v;
	int* dindx = new int[3];

	dindx[0] = ((x - xMin) / 0.005) +0.5;
	dindx[1] = ((y - yMin) / 0.005) +0.5;
	dindx[2] = ((z - zMin) / 0.005) +0.5;

	v = dindx;
	return v;
}

vmml::vec3d ImportData::getPoint(int x, int y, int z){
	double xMin = -0.0475;
	double yMin = -0.0475;
	double zMin = -0.0975;

	vmml::vec3d v = vmml::vec3d(xMin + x*0.005,
								yMin + y*0.005,
								zMin + z*0.005);
	
	//v->at(0) = (x*0.005) + xMin;
	//v->at(1) = (y*0.005) + yMin;
	//v->at(2) = (z*0.005) + zMin;


	return v;
}

Eigen::VectorXd ImportData::getPoint_Eigen(int x, int y, int z){
	double xMin = -0.0475;
	double yMin = -0.0475;
	double zMin = -0.0975;

	Vector3d v;
	v << xMin + x*0.005,
		 yMin + y*0.005,
		 zMin + z*0.005;
	
	//v->at(0) = (x*0.005) + xMin;
	//v->at(1) = (y*0.005) + yMin;
	//v->at(2) = (z*0.005) + zMin;


	return v;
}

void ImportData::initialize(string path){
	int lines = countLines(path);
	this->setSize(lines);
	string** newdata = new string*[lines];
	for(int i = 0; i < lines ; i++){
			newdata[i] = new string[17];
	}
	this->data = newdata;
	readFile(path);
}

string** ImportData::getData(){
	return this->data;
}

DataPoint*** ImportData::getVolume(){
	return this->volume;
}

int ImportData::countLines(string path){
	cout << "Counting lines in dataset.." << endl;
	const char * cpath = path.c_str();
	ifstream myfile (cpath);
	string line;
	int linenumb = 0;
	if (myfile.is_open()){
		while ( myfile.good() ){
			getline (myfile,line);
			linenumb++;
		}
    myfile.close();
	}
	cout << "Number of lines: " << linenumb << endl;
	return linenumb;
}

void ImportData::readFile(string path){
  cout << "Reading Data From File.." << endl;
  string line;
  string segment;
  int lnumber = 0;
  bool commafound = false;
  const char * cpath = path.c_str();
  ifstream myfile (cpath);
  if (myfile.is_open()){
    while ( myfile.good() ){
		getline (myfile,line);
		int j = 0;
		for (int i=0;i<17;i++){
			while(!commafound){
				segment += line[j];
				j++;
				if(line[j] == ';'){
					commafound = true;
					j++;
				}
			}
		this->data[lnumber][i] = segment;
		segment = "";
		commafound = false;
		}
		lnumber++;
	}
    myfile.close();
	cout << "Done.." << endl;
  }

  else cout << "ERROR: Unable to open file \n"; 

}

ImportData::~ImportData(void)
{
	delete data;
	delete volume;

}


